package org.zzh.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.logging.log4j.Log4jImpl;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.Objects;
import java.util.Properties;


/**
 * @author 十里坡
 * @description 配置 MyBatis
 */
@Configuration
@MapperScan("org.zzh.dao.mapper") // 扫描 MyBatis 的 Mapper 接口
@PropertySource("classpath:jdbc.properties")
public class MybatisConfig {

    @Autowired
    private Environment environment;


    /**
     * 配置并创建数据源Bean
     * 本方法使用Druid数据源，并从环境变量中读取数据库连接信息及连接池参数
     * @return DataSource 数据源实例
     */
    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();

        // 从配置文件中读取数据库连接信息
        dataSource.setDriverClassName(environment.getProperty("jdbc.driver"));
        dataSource.setUrl(environment.getProperty("jdbc.url"));
        dataSource.setUsername(environment.getProperty("jdbc.username"));
        dataSource.setPassword(environment.getProperty("jdbc.password"));

        // 从配置文件中读取连接池参数
        dataSource.setInitialSize(Integer.parseInt(Objects.requireNonNull(environment.getProperty("jdbc.initialSize"))));
        dataSource.setMinIdle(Integer.parseInt(Objects.requireNonNull(environment.getProperty("jdbc.minIdle"))));
        dataSource.setMaxActive(Integer.parseInt(Objects.requireNonNull(environment.getProperty("jdbc.maxActive"))));
        dataSource.setMaxWait(Long.parseLong(Objects.requireNonNull(environment.getProperty("jdbc.maxWait"))));
        dataSource.setTimeBetweenEvictionRunsMillis(Long.parseLong(Objects.requireNonNull(environment.getProperty("jdbc.timeBetweenEvictionRunsMillis"))));
        dataSource.setMinEvictableIdleTimeMillis(Long.parseLong(Objects.requireNonNull(environment.getProperty("jdbc.minEvictableIdleTimeMillis"))));
        dataSource.setValidationQuery(environment.getProperty("jdbc.validationQuery"));
        dataSource.setTestWhileIdle(Boolean.parseBoolean(environment.getProperty("jdbc.testWhileIdle")));
        dataSource.setTestOnBorrow(Boolean.parseBoolean(environment.getProperty("jdbc.testOnBorrow")));
        dataSource.setTestOnReturn(Boolean.parseBoolean(environment.getProperty("jdbc.testOnReturn")));

        return dataSource;
    }


    /**
     * 创建并配置 SqlSessionFactoryBean 实例
     *
     * @return SqlSessionFactoryBean 实例，已配置数据源、类型别名包、配置属性和映射文件路径
     * @throws IOException 当解析映射文件路径出现问题时抛出此异常
     */
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean() throws IOException {
        // 创建 SqlSessionFactoryBean 对象
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        // 设置数据源
        sqlSessionFactoryBean.setDataSource(dataSource());
        // 设置 MyBatis 的类型别名包
        sqlSessionFactoryBean.setTypeAliasesPackage("org.zzh.domain");

        // 创建 MyBatis 配置对象
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        // 开启驼峰命名法转换，以匹配 Java 属性命名规范
        configuration.setMapUnderscoreToCamelCase(true);
        // 设置日志实现
        configuration.setLogImpl(Log4jImpl.class);
        // 将配置对象设置到 SqlSessionFactoryBean
        sqlSessionFactoryBean.setConfiguration(configuration);

        // 使用 PathMatchingResourcePatternResolver 解析资源路径
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        // 解析映射文件路径，获取资源列表
        Resource[] resources = resolver.getResources("classpath*:org/zzh/dao/mapper/*.xml");
        // 设置映射文件路径
        sqlSessionFactoryBean.setMapperLocations(resources);

        // 添加分页插件
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties properties = new Properties();
        properties.setProperty("reasonable", "true");
        pageInterceptor.setProperties(properties);
        sqlSessionFactoryBean.setPlugins(new PageInterceptor[]{pageInterceptor});


        // 返回配置好的 SqlSessionFactoryBean 实例
        return sqlSessionFactoryBean;
    }


}